home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / C++ / DirectInput / ActionMapper / diutil.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-09-27  |  11.2 KB  |  361 lines

  1. //-----------------------------------------------------------------------------
  2. // File: DIUtil.cpp
  3. //
  4. // Desc: DirectInput framework class using semantic mapping.  Feel free to use 
  5. //       this class as a starting point for adding extra functionality.
  6. //
  7. // Copyright (C) Microsoft Corporation. All Rights Reserved.
  8. //-----------------------------------------------------------------------------
  9. #define STRICT
  10.  
  11. #include <basetsd.h>
  12. #include <tchar.h>
  13. #include <stdio.h>
  14. #include "DIUtil.h"
  15.  
  16.  
  17.  
  18.  
  19.  
  20. //-----------------------------------------------------------------------------
  21. // Name: CInputDeviceManager()
  22. // Desc: Constructor 
  23. //-----------------------------------------------------------------------------
  24. CInputDeviceManager::CInputDeviceManager()
  25. {
  26.     HRESULT hr = CoInitialize(NULL);
  27.     m_bCleanupCOM = SUCCEEDED(hr);
  28.  
  29.     m_dwNumDevices = 0;
  30.     m_dwMaxDevices = 10;
  31.     m_pDI          = NULL;
  32.  
  33.     // Allocate DeviceInfo structs
  34.     m_pDevices = (DeviceInfo*) malloc( m_dwMaxDevices*sizeof(DeviceInfo) );
  35.     if( m_pDevices )
  36.         ZeroMemory( m_pDevices, m_dwMaxDevices*sizeof(DeviceInfo) );
  37. }
  38.  
  39.  
  40.  
  41.  
  42. //-----------------------------------------------------------------------------
  43. // Name: ~CInputDeviceManager()
  44. // Desc: Destructor
  45. //-----------------------------------------------------------------------------
  46. CInputDeviceManager::~CInputDeviceManager()
  47. {
  48.     if( m_pDevices )
  49.     {
  50.         // Release() all devices
  51.         for( DWORD i=0; i<m_dwNumDevices; i++ )
  52.         {
  53.             if( m_pDevices[i].pdidDevice )
  54.                 m_pDevices[i].pdidDevice->Unacquire();
  55.  
  56.             SAFE_RELEASE( m_pDevices[i].pdidDevice );
  57.         }
  58.  
  59.         free( m_pDevices );
  60.     }
  61.  
  62.     // Release() base object
  63.     SAFE_RELEASE( m_pDI );
  64.  
  65.     if( m_bCleanupCOM )
  66.         CoUninitialize();
  67. }
  68.  
  69.  
  70.  
  71.  
  72. //-----------------------------------------------------------------------------
  73. // Name: GetDevices()
  74. // Desc: Get the DeviceInfo array and number of devices
  75. //-----------------------------------------------------------------------------
  76. HRESULT CInputDeviceManager::GetDevices( DeviceInfo** ppDeviceInfo, 
  77.                                          DWORD* pdwCount )
  78. {
  79.     if( NULL==ppDeviceInfo || NULL==pdwCount )
  80.         return E_INVALIDARG;
  81.  
  82.     (*ppDeviceInfo) = m_pDevices;
  83.     (*pdwCount) = m_dwNumDevices;
  84.  
  85.     return S_OK;
  86. }
  87.  
  88.  
  89.  
  90.  
  91. //-----------------------------------------------------------------------------
  92. // Name: AddDevice()
  93. // Desc: Add the provided device to the list and perform initialization
  94. //-----------------------------------------------------------------------------
  95. HRESULT CInputDeviceManager::AddDevice( const DIDEVICEINSTANCE* pdidi, 
  96.                                         const LPDIRECTINPUTDEVICE8 pdidDevice )
  97. {
  98.     HRESULT hr;
  99.  
  100.     // Sanity check
  101.     if( NULL == pdidDevice )
  102.         return E_INVALIDARG;
  103.  
  104.     pdidDevice->Unacquire();
  105.  
  106.     // Set the device's coop level
  107.     hr = pdidDevice->SetCooperativeLevel( m_hWnd, DISCL_NONEXCLUSIVE|DISCL_FOREGROUND );
  108.     if( FAILED(hr) )
  109.         return hr;
  110.  
  111.     // Enlarge the array if needed
  112.     if( m_dwNumDevices >= m_dwMaxDevices )
  113.     {
  114.         // Attempt to reallocate memory
  115.         DWORD dwNewMax = m_dwMaxDevices + 10;
  116.         DeviceInfo* pNewDevices = (DeviceInfo*) realloc( m_pDevices, sizeof(DeviceInfo) * dwNewMax );
  117.         
  118.         // Check for out of memory condition
  119.         if( NULL == pNewDevices )
  120.             return E_OUTOFMEMORY;
  121.  
  122.         // Initialize the new memory block
  123.         ZeroMemory( pNewDevices + m_dwMaxDevices, sizeof(DeviceInfo) * (dwNewMax - m_dwMaxDevices) );
  124.  
  125.         // Copy the new pointer and update the max device count
  126.         m_pDevices = pNewDevices;
  127.         m_dwMaxDevices = dwNewMax;
  128.     }
  129.  
  130.     // Add new device to the end of the list, but don't finalize addition until
  131.     // the end of the function. If the remaining initialization calls fail, this
  132.     // spot will be used by the next valid device.
  133.     m_pDevices[m_dwNumDevices].pdidDevice = pdidDevice;
  134.  
  135.     // Build the action map
  136.     hr = m_pDevices[m_dwNumDevices].pdidDevice->BuildActionMap( &m_diaf, m_strUserName, 0 );
  137.     if( FAILED(hr) )
  138.         return hr;
  139.  
  140.     // Set the action map for the current device
  141.     hr = m_pDevices[m_dwNumDevices].pdidDevice->SetActionMap( &m_diaf, m_strUserName, 0 );
  142.     if( FAILED(hr) )
  143.         return hr;
  144.  
  145.     // Callback into the app so it can adjust the device and set
  146.     // the m_pDevices[dwCurrentDevice].pParam field with a device state struct
  147.     if( m_AddDeviceCallback )
  148.     {
  149.         hr = m_AddDeviceCallback( &m_pDevices[m_dwNumDevices], pdidi, m_AddDeviceCallbackParam ); 
  150.         if( FAILED(hr) )    
  151.             return hr;
  152.     }
  153.  
  154.     // Device addition succeeded. Increment reference and index.
  155.     m_pDevices[m_dwNumDevices].pdidDevice->AddRef();
  156.     m_dwNumDevices++;
  157.  
  158.     // Continue enumerating suitable devices
  159.     return S_OK;
  160. }
  161.  
  162.  
  163.  
  164.  
  165. //-----------------------------------------------------------------------------
  166. // Name: EnumSuitableDevicesCB()
  167. // Desc: Callback function for device enumeration. Adds all devices which
  168. //       met the search criteria
  169. //-----------------------------------------------------------------------------
  170. BOOL CALLBACK EnumSuitableDevicesCB( LPCDIDEVICEINSTANCE pdidi, 
  171.                                      LPDIRECTINPUTDEVICE8 pdidDevice, 
  172.                                      DWORD dwFlags, DWORD dwDeviceRemaining,
  173.                                      VOID* pContext )
  174. {
  175.     UNREFERENCED_PARAMETER( dwFlags );
  176.     UNREFERENCED_PARAMETER( dwDeviceRemaining );
  177.     
  178.     // Add the device to the device manager's internal list
  179.     ((CInputDeviceManager*)pContext)->AddDevice( pdidi, pdidDevice );
  180.  
  181.     // Continue enumerating suitable devices
  182.     return DIENUM_CONTINUE;
  183. }
  184.  
  185.  
  186.  
  187.  
  188. //-----------------------------------------------------------------------------
  189. // Name: SetActionFormat()
  190. // Desc: Set the action format to the provided DIACTIONFORMAT structure, and
  191. //       destroy and recreate device list if flagged
  192. //-----------------------------------------------------------------------------
  193. HRESULT CInputDeviceManager::SetActionFormat( DIACTIONFORMAT& diaf, BOOL bReenumerate )
  194. {
  195.     HRESULT hr = S_OK;
  196.  
  197.     // Store the new action format
  198.     m_diaf = diaf;
  199.  
  200.     // Only destroy and re-enumerate devices if the caller explicitly wants to. The 
  201.     // device list may be used within a loop, and kicking off an enumeration while 
  202.     // the device array is in use would cause problems.
  203.     if( bReenumerate )
  204.     {
  205.         // Cleanup any previously enumerated devices
  206.         for( DWORD i=0; i<m_dwNumDevices; i++ )
  207.         {
  208.             if( m_pDevices[i].pdidDevice )
  209.                 m_pDevices[i].pdidDevice->Unacquire();
  210.  
  211.             SAFE_RELEASE( m_pDevices[i].pdidDevice );
  212.         }
  213.         m_dwNumDevices = 0;
  214.  
  215.         // Enumerate suitable DirectInput devices
  216.         hr = m_pDI->EnumDevicesBySemantics( m_strUserName, &m_diaf, 
  217.                                             EnumSuitableDevicesCB, this, 0L );
  218.         if( FAILED(hr) )
  219.             return hr;
  220.     }
  221.     else // Just apply the new maps.
  222.     {
  223.         // Devices must be unacquired to have a new action map set.
  224.         UnacquireDevices();
  225.  
  226.         // Apply the new action map to the current devices.
  227.         for( DWORD i=0; i<m_dwNumDevices; i++ )
  228.         {
  229.             hr = m_pDevices[i].pdidDevice->BuildActionMap( &m_diaf, m_strUserName, 0 );
  230.             if( FAILED(hr) )
  231.                 return hr;
  232.  
  233.             hr = m_pDevices[i].pdidDevice->SetActionMap( &m_diaf, m_strUserName, 0 );
  234.             if( FAILED(hr) )
  235.                 return hr;
  236.         }
  237.     }
  238.  
  239.     return S_OK;
  240. }
  241.  
  242.  
  243.  
  244.  
  245. //-----------------------------------------------------------------------------
  246. // Name: Create()
  247. // Desc: Create DirectInput object and perform initialization
  248. //-----------------------------------------------------------------------------
  249. HRESULT CInputDeviceManager::Create( HWND hWnd, TCHAR* strUserName, 
  250.                                      DIACTIONFORMAT& diaf,
  251.                                      LPDIMANAGERCALLBACK AddDeviceCallback, 
  252.                                      LPVOID pCallbackParam )
  253. {
  254.     HRESULT hr;
  255.  
  256.     // Store data
  257.     m_hWnd        = hWnd;
  258.     m_strUserName = strUserName;
  259.     m_AddDeviceCallback = AddDeviceCallback;
  260.     m_AddDeviceCallbackParam = pCallbackParam;
  261.     
  262.     // Create the base DirectInput object
  263.     hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION, 
  264.                               IID_IDirectInput8, (VOID**)&m_pDI, NULL );
  265.     if( FAILED(hr) )
  266.         return hr;
  267.  
  268.     hr = SetActionFormat( diaf, TRUE );
  269.     if( FAILED(hr) )
  270.         return hr;
  271.  
  272.     return S_OK;
  273. }
  274.  
  275.  
  276.  
  277.  
  278. //-----------------------------------------------------------------------------
  279. // Name: ConfigureDevices()
  280. // Desc: Pause input and display the device configuration UI
  281. //-----------------------------------------------------------------------------
  282. HRESULT CInputDeviceManager::ConfigureDevices( HWND hWnd, IUnknown* pSurface,
  283.                                                VOID* ConfigureDevicesCB,
  284.                                                DWORD dwFlags, LPVOID pvCBParam )
  285. {
  286.     HRESULT hr;
  287.  
  288.     // Initialize all the colors here
  289.     DICOLORSET dics;
  290.     ZeroMemory(&dics, sizeof(DICOLORSET));
  291.     dics.dwSize = sizeof(DICOLORSET);
  292.  
  293.     // Fill in all the params
  294.     DICONFIGUREDEVICESPARAMS dicdp;
  295.     ZeroMemory(&dicdp, sizeof(dicdp));
  296.     dicdp.dwSize = sizeof(dicdp);
  297.     dicdp.dwcFormats     = 1;
  298.     dicdp.lprgFormats    = &m_diaf;
  299.     dicdp.hwnd           = hWnd;
  300.     dicdp.lpUnkDDSTarget = pSurface;
  301.  
  302.     if( m_strUserName )
  303.     {
  304.         dicdp.dwcUsers       = 1;
  305.         dicdp.lptszUserNames = m_strUserName;
  306.     }
  307.  
  308.     // Unacquire the devices so that mouse doesn't control the game while in control panel
  309.     UnacquireDevices();
  310.  
  311.     hr = m_pDI->ConfigureDevices( (LPDICONFIGUREDEVICESCALLBACK)ConfigureDevicesCB, 
  312.                                   &dicdp, dwFlags, pvCBParam );
  313.     if( FAILED(hr) )
  314.         return hr;
  315.  
  316.     if( dwFlags & DICD_EDIT )
  317.     {
  318.         // Re-set up the devices
  319.         hr = SetActionFormat( m_diaf, TRUE );
  320.         if( FAILED(hr) )
  321.             return hr;
  322.     }
  323.  
  324.     return S_OK;
  325. }
  326.  
  327.  
  328.  
  329. //-----------------------------------------------------------------------------
  330. // Name: UnacquireDevices()
  331. // Desc: Unacquire all devices in the member list
  332. //-----------------------------------------------------------------------------
  333. VOID CInputDeviceManager::UnacquireDevices()
  334. {
  335.     for( DWORD i=0; i<m_dwNumDevices; i++ )
  336.         m_pDevices[i].pdidDevice->Unacquire();
  337. }
  338.  
  339.  
  340.  
  341.  
  342. //-----------------------------------------------------------------------------
  343. // Name: SetFocus()
  344. // Desc: Sets the DirectInput focus to a new HWND
  345. //-----------------------------------------------------------------------------
  346. VOID CInputDeviceManager::SetFocus( HWND hWnd ) 
  347. {
  348.     m_hWnd = hWnd;
  349.  
  350.     UnacquireDevices();
  351.  
  352.     for( DWORD i=0; i<m_dwNumDevices; i++ )
  353.     {
  354.         // Set the device's coop level
  355.         m_pDevices[i].pdidDevice->SetCooperativeLevel( m_hWnd, 
  356.                                         DISCL_NONEXCLUSIVE|DISCL_FOREGROUND );
  357.     }
  358. }
  359.  
  360.  
  361.